package com.shrct.businessprocess.purchase.impl;

import com.google.common.base.Objects;
import com.google.common.collect.Iterables;
import com.shrct.businessprocess.money.Moneys;
import com.shrct.businessprocess.organization.RCEnterprise;
import com.shrct.businessprocess.project.RCCustomerContract;
import com.shrct.businessprocess.project.RCCustomerContractMoneyAccept;
import com.shrct.businessprocess.project.RCCustomerContractMoneyAcceptAssignment;
import com.shrct.businessprocess.project.RCExchangeRate;
import com.shrct.businessprocess.project.RCProject;
import com.shrct.businessprocess.project.RCProjectMoney;
import com.shrct.businessprocess.project.RCRealMoney;
import com.shrct.businessprocess.project.impl.RCCustomerContractImpl;
import com.shrct.businessprocess.project.impl.RCProjectImpl;
import com.shrct.businessprocess.purchase.RCGeneralInvoiceType;
import com.shrct.businessprocess.purchase.RCInvoiceAccountInfo;
import com.shrct.businessprocess.purchase.RCInvoiceCondition;
import com.shrct.businessprocess.purchase.RCInvoiceType;
import com.shrct.businessprocess.purchase.RCPurchaseIncomeProcess;
import com.shrct.businessprocess.purchase.RCPurchaseIncomeRequest;
import com.shrct.businessprocess.purchase.RCPurchaseInvoiceItem;
import com.shrct.businessprocess.purchase.impl.RCPurchaseInvoiceItemImpl;
import com.shrct.businessprocess.purchase.proxy.RCPurchaseIncomeRequestProxy;
import edu.fudan.mylang.common.NumberExtensions;
import edu.fudan.mylang.pf.BaseModelObject;
import edu.fudan.mylang.pf.IGenericQuery;
import edu.fudan.mylang.pf.IObjectFactory;
import java.util.Collection;
import java.util.Date;
import javax.persistence.AssociationOverride;
import javax.persistence.AssociationOverrides;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorValue;
import javax.persistence.ElementCollection;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.eclipse.xtext.xbase.lib.DoubleExtensions;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.Functions.Function2;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.hibernate.annotations.DiscriminatorOptions;

@Entity
@DiscriminatorValue("RCPURCHASEINCOMEREQUEST_TYPE")
@DiscriminatorOptions(force = true)
@DiscriminatorColumn(length = 64)
@Table(name = "rcpurchaseincomerequest")
public class RCPurchaseIncomeRequestImpl extends BaseModelObject implements RCPurchaseIncomeRequest {
  public RCPurchaseIncomeRequestImpl() {
    super();
  }
  
  @JoinColumn(name = "project_id")
  @ManyToOne(targetEntity = RCProjectImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCProject project;
  
  public RCProject getProject() {
    return this.project;
  }
  
  public RCPurchaseIncomeRequest setProject(final RCProject project) {
    this.project = project;
    return this;			
    
  }
  
  @JoinColumn(name = "customerContract_id")
  @ManyToOne(targetEntity = RCCustomerContractImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCCustomerContract customerContract;
  
  public RCCustomerContract getCustomerContract() {
    return this.customerContract;
  }
  
  public RCPurchaseIncomeRequest setCustomerContract(final RCCustomerContract customerContract) {
    this.customerContract = customerContract;
    return this;			
    
  }
  
  private String invoiceTitle;
  
  public String getInvoiceTitle() {
    return this.invoiceTitle;
  }
  
  public RCPurchaseIncomeRequest setInvoiceTitle(final String invoiceTitle) {
    this.invoiceTitle = invoiceTitle;
    return this;			
    
  }
  
  private String content;
  
  public String getContent() {
    return this.content;
  }
  
  public RCPurchaseIncomeRequest setContent(final String content) {
    this.content = content;
    return this;			
    
  }
  
  private String comment;
  
  public String getComment() {
    return this.comment;
  }
  
  public RCPurchaseIncomeRequest setComment(final String comment) {
    this.comment = comment;
    return this;			
    
  }
  
  @Embedded
  @AttributeOverrides(value = { @AttributeOverride(name = "amount", column = @Column(name = "amount_amount") ), @AttributeOverride(name = "workaround", column = @Column(name = "amount_workaround") ) } )
  @AssociationOverrides(value = @AssociationOverride(name = "exchange", joinColumns = @JoinColumn(name = "amount_exchange") ) )
  private RCProjectMoney amount = com.shrct.businessprocess.project.RCProjectMoney.create();
  
  public RCProjectMoney getAmount() {
    return this.amount;
  }
  
  public RCPurchaseIncomeRequest setAmount(final RCProjectMoney amount) {
    this.amount = amount;
    return this;			
    
  }
  
  private String invoiceNumber;
  
  public String getInvoiceNumber() {
    return this.invoiceNumber;
  }
  
  public RCPurchaseIncomeRequest setInvoiceNumber(final String invoiceNumber) {
    this.invoiceNumber = invoiceNumber;
    return this;			
    
  }
  
  private Date passDate;
  
  public Date getPassDate() {
    return this.passDate;
  }
  
  public RCPurchaseIncomeRequest setPassDate(final Date passDate) {
    this.passDate = passDate;
    return this;			
    
  }
  
  private Boolean isPassed = Boolean.valueOf(false);
  
  public Boolean getIsPassed() {
    return this.isPassed;
  }
  
  public RCPurchaseIncomeRequest setIsPassed(final Boolean isPassed) {
    this.isPassed = isPassed;
    return this;			
    
  }
  
  @Embedded
  @AttributeOverrides(value = { @AttributeOverride(name = "companyName", column = @Column(name = "customerInvoiceAccountInfo_companyName") ), @AttributeOverride(name = "registerCode", column = @Column(name = "customerInvoiceAccountInfo_registerCode") ), @AttributeOverride(name = "address", column = @Column(name = "customerInvoiceAccountInfo_address") ), @AttributeOverride(name = "phone", column = @Column(name = "customerInvoiceAccountInfo_phone") ), @AttributeOverride(name = "accountDetail", column = @Column(name = "customerInvoiceAccountInfo_accountDetail") ), @AttributeOverride(name = "workaround", column = @Column(name = "customerInvoiceAccountInfo_workaround") ) } )
  @AssociationOverrides(value = { } )
  private RCInvoiceAccountInfo customerInvoiceAccountInfo = com.shrct.businessprocess.purchase.RCInvoiceAccountInfo.create();
  
  public RCInvoiceAccountInfo getCustomerInvoiceAccountInfo() {
    return this.customerInvoiceAccountInfo;
  }
  
  public RCPurchaseIncomeRequest setCustomerInvoiceAccountInfo(final RCInvoiceAccountInfo customerInvoiceAccountInfo) {
    this.customerInvoiceAccountInfo = customerInvoiceAccountInfo;
    return this;			
    
  }
  
  @Embedded
  @AttributeOverrides(value = { @AttributeOverride(name = "companyName", column = @Column(name = "companyInvoiceAccountInfo_companyName") ), @AttributeOverride(name = "registerCode", column = @Column(name = "companyInvoiceAccountInfo_registerCode") ), @AttributeOverride(name = "address", column = @Column(name = "companyInvoiceAccountInfo_address") ), @AttributeOverride(name = "phone", column = @Column(name = "companyInvoiceAccountInfo_phone") ), @AttributeOverride(name = "accountDetail", column = @Column(name = "companyInvoiceAccountInfo_accountDetail") ), @AttributeOverride(name = "workaround", column = @Column(name = "companyInvoiceAccountInfo_workaround") ) } )
  @AssociationOverrides(value = { } )
  private RCInvoiceAccountInfo companyInvoiceAccountInfo = com.shrct.businessprocess.purchase.RCInvoiceAccountInfo.create();
  
  public RCInvoiceAccountInfo getCompanyInvoiceAccountInfo() {
    return this.companyInvoiceAccountInfo;
  }
  
  public RCPurchaseIncomeRequest setCompanyInvoiceAccountInfo(final RCInvoiceAccountInfo companyInvoiceAccountInfo) {
    this.companyInvoiceAccountInfo = companyInvoiceAccountInfo;
    return this;			
    
  }
  
  private RCGeneralInvoiceType generalInvoiceType;
  
  public RCGeneralInvoiceType getGeneralInvoiceType() {
    return this.generalInvoiceType;
  }
  
  public RCPurchaseIncomeRequest setGeneralInvoiceType(final RCGeneralInvoiceType generalInvoiceType) {
    this.generalInvoiceType = generalInvoiceType;
    return this;			
    
  }
  
  @ElementCollection
  private Collection<RCInvoiceType> invoiceType = new java.util.ArrayList<com.shrct.businessprocess.purchase.RCInvoiceType>();;
  
  public Collection<RCInvoiceType> getInvoiceType() {
    return this.invoiceType;
  }
  
  public RCPurchaseIncomeRequest setInvoiceType(final Iterable<RCInvoiceType> invoiceType) {
    removeAllInvoiceType();
    for(RCInvoiceType ca : invoiceType){
    	addtoInvoiceType(ca);
    }
    return this;		
    
  }
  
  public RCPurchaseIncomeRequest addtoInvoiceType(final RCInvoiceType rCInvoiceType) {
    this.invoiceType.add(rCInvoiceType);
    return this;
    
  }
  
  public RCPurchaseIncomeRequest removeAllInvoiceType() {
    this.invoiceType.clear();
    return this;	
    
  }
  
  public RCPurchaseIncomeRequest removeFromInvoiceType(final RCInvoiceType rCInvoiceType) {
    this.invoiceType.remove(rCInvoiceType);
    return this;
    
  }
  
  @ElementCollection
  private Collection<RCInvoiceCondition> invoiceCondition = new java.util.ArrayList<com.shrct.businessprocess.purchase.RCInvoiceCondition>();;
  
  public Collection<RCInvoiceCondition> getInvoiceCondition() {
    return this.invoiceCondition;
  }
  
  public RCPurchaseIncomeRequest setInvoiceCondition(final Iterable<RCInvoiceCondition> invoiceCondition) {
    removeAllInvoiceCondition();
    for(RCInvoiceCondition ca : invoiceCondition){
    	addtoInvoiceCondition(ca);
    }
    return this;		
    
  }
  
  public RCPurchaseIncomeRequest addtoInvoiceCondition(final RCInvoiceCondition rCInvoiceCondition) {
    this.invoiceCondition.add(rCInvoiceCondition);
    return this;
    
  }
  
  public RCPurchaseIncomeRequest removeAllInvoiceCondition() {
    this.invoiceCondition.clear();
    return this;	
    
  }
  
  public RCPurchaseIncomeRequest removeFromInvoiceCondition(final RCInvoiceCondition rCInvoiceCondition) {
    this.invoiceCondition.remove(rCInvoiceCondition);
    return this;
    
  }
  
  private String invoiceMailAddress;
  
  public String getInvoiceMailAddress() {
    return this.invoiceMailAddress;
  }
  
  public RCPurchaseIncomeRequest setInvoiceMailAddress(final String invoiceMailAddress) {
    this.invoiceMailAddress = invoiceMailAddress;
    return this;			
    
  }
  
  private String invoiceMailName;
  
  public String getInvoiceMailName() {
    return this.invoiceMailName;
  }
  
  public RCPurchaseIncomeRequest setInvoiceMailName(final String invoiceMailName) {
    this.invoiceMailName = invoiceMailName;
    return this;			
    
  }
  
  private String receiver;
  
  public String getReceiver() {
    return this.receiver;
  }
  
  public RCPurchaseIncomeRequest setReceiver(final String receiver) {
    this.receiver = receiver;
    return this;			
    
  }
  
  private String postCode;
  
  public String getPostCode() {
    return this.postCode;
  }
  
  public RCPurchaseIncomeRequest setPostCode(final String postCode) {
    this.postCode = postCode;
    return this;			
    
  }
  
  private String phone;
  
  public String getPhone() {
    return this.phone;
  }
  
  public RCPurchaseIncomeRequest setPhone(final String phone) {
    this.phone = phone;
    return this;			
    
  }
  
  @OneToMany(targetEntity = RCPurchaseInvoiceItemImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, mappedBy = "incomeRequest")
  private Collection<RCPurchaseInvoiceItem> items = new java.util.ArrayList<com.shrct.businessprocess.purchase.RCPurchaseInvoiceItem>();;
  
  public Collection<RCPurchaseInvoiceItem> getItems() {
    return this.items;
  }
  
  public RCPurchaseInvoiceItem createAndAddtoItems() {
    getItems().size();
    com.shrct.businessprocess.purchase.RCPurchaseInvoiceItem rCPurchaseInvoiceItem = new com.shrct.businessprocess.purchase.impl.RCPurchaseInvoiceItemImpl(this);
    getObjectFactory().create(rCPurchaseInvoiceItem);
    getItems().add(rCPurchaseInvoiceItem);
    return rCPurchaseInvoiceItem;
    
  }
  
  public RCPurchaseInvoiceItem createAndAddtoItems(final Procedure1<RCPurchaseInvoiceItem> updater) {
    getItems().size();
    com.shrct.businessprocess.purchase.RCPurchaseInvoiceItem rCPurchaseInvoiceItem = new com.shrct.businessprocess.purchase.impl.RCPurchaseInvoiceItemImpl(this);
    getObjectFactory().create(rCPurchaseInvoiceItem);
    getItems().add(rCPurchaseInvoiceItem);
    return rCPurchaseInvoiceItem;
    
  }
  
  public RCPurchaseIncomeRequest removeAllItems() {
    for(RCPurchaseInvoiceItem obj : this.items){
    	getObjectFactory().delete(obj);
    }
    this.items.clear();
    return this;	
    
  }
  
  public RCPurchaseIncomeRequest removeFromItems(final RCPurchaseInvoiceItem rCPurchaseInvoiceItem) {
    this.items.remove(rCPurchaseInvoiceItem);
    getObjectFactory().delete(rCPurchaseInvoiceItem);
    return this;
    
  }
  
  public Boolean isCanceled() {
    boolean _and = false;
    RCPurchaseIncomeProcess _process = this.getProcess();
    Boolean _isFinished = _process.getIsFinished();
    if (!(_isFinished).booleanValue()) {
      _and = false;
    } else {
      boolean _not = (!this.isPassed);
      _and = ((_isFinished).booleanValue() && _not);
    }
    return Boolean.valueOf(_and);
  }
  
  public Boolean getAllPaid() {
    Double _remainAmount = this.getRemainAmount();
    boolean _lessEqualsThan = ((_remainAmount).doubleValue() <= 0);
    return Boolean.valueOf(_lessEqualsThan);
  }
  
  public Double getActualIncome() {
    final Function1<RCPurchaseInvoiceItem,Double> _function = new Function1<RCPurchaseInvoiceItem,Double>() {
        public Double apply(final RCPurchaseInvoiceItem it) {
          Double _actualIncome = it.getActualIncome();
          return _actualIncome;
        }
      };
    Iterable<Double> _map = IterableExtensions.<RCPurchaseInvoiceItem, Double>map(this.items, _function);
    final Function2<Double,Double,Double> _function_1 = new Function2<Double,Double,Double>() {
        public Double apply(final Double d1, final Double d2) {
          double _plus = DoubleExtensions.operator_plus(d1, d2);
          return Double.valueOf(_plus);
        }
      };
    Double _reduce = IterableExtensions.<Double>reduce(_map, _function_1);
    Double _nullsafe = NumberExtensions.nullsafe(_reduce);
    return _nullsafe;
  }
  
  public Double getActualTax() {
    final Function1<RCPurchaseInvoiceItem,Double> _function = new Function1<RCPurchaseInvoiceItem,Double>() {
        public Double apply(final RCPurchaseInvoiceItem it) {
          Double _actualTax = it.getActualTax();
          return _actualTax;
        }
      };
    Iterable<Double> _map = IterableExtensions.<RCPurchaseInvoiceItem, Double>map(this.items, _function);
    final Function2<Double,Double,Double> _function_1 = new Function2<Double,Double,Double>() {
        public Double apply(final Double d1, final Double d2) {
          double _plus = DoubleExtensions.operator_plus(d1, d2);
          return Double.valueOf(_plus);
        }
      };
    Double _reduce = IterableExtensions.<Double>reduce(_map, _function_1);
    Double _nullsafe = NumberExtensions.nullsafe(_reduce);
    return _nullsafe;
  }
  
  public RCEnterprise getCustomer() {
    RCEnterprise _customer = this.customerContract.getCustomer();
    return _customer;
  }
  
  public Double getRemainAmount() {
    double _xblockexpression = (double) 0;
    {
      Double _hostAmount = this.amount.toHostAmount();
      RCRealMoney _totalAssignedAmount = this.getTotalAssignedAmount();
      Double _hostAmount_1 = _totalAssignedAmount.toHostAmount();
      final double result = DoubleExtensions.operator_minus(_hostAmount, _hostAmount_1);
      _xblockexpression = (result);
    }
    return Double.valueOf(_xblockexpression);
  }
  
  public RCRealMoney getTotalAssignedAmount() {
    RCRealMoney _xblockexpression = null;
    {
      Collection<RCCustomerContractMoneyAccept> _moneyAccepts = this.customerContract.getMoneyAccepts();
      final Function1<RCCustomerContractMoneyAccept,Collection<RCCustomerContractMoneyAcceptAssignment>> _function = new Function1<RCCustomerContractMoneyAccept,Collection<RCCustomerContractMoneyAcceptAssignment>>() {
          public Collection<RCCustomerContractMoneyAcceptAssignment> apply(final RCCustomerContractMoneyAccept it) {
            Collection<RCCustomerContractMoneyAcceptAssignment> _assignments = it.getAssignments();
            return _assignments;
          }
        };
      Iterable<Collection<RCCustomerContractMoneyAcceptAssignment>> _map = IterableExtensions.<RCCustomerContractMoneyAccept, Collection<RCCustomerContractMoneyAcceptAssignment>>map(_moneyAccepts, _function);
      Iterable<RCCustomerContractMoneyAcceptAssignment> _flatten = Iterables.<RCCustomerContractMoneyAcceptAssignment>concat(_map);
      final Function1<RCCustomerContractMoneyAcceptAssignment,Boolean> _function_1 = new Function1<RCCustomerContractMoneyAcceptAssignment,Boolean>() {
          public Boolean apply(final RCCustomerContractMoneyAcceptAssignment assignment) {
            RCPurchaseIncomeRequest _income = assignment.getIncome();
            boolean _equals = Objects.equal(_income, RCPurchaseIncomeRequestImpl.this);
            return Boolean.valueOf(_equals);
          }
        };
      Iterable<RCCustomerContractMoneyAcceptAssignment> _filter = IterableExtensions.<RCCustomerContractMoneyAcceptAssignment>filter(_flatten, _function_1);
      final Function1<RCCustomerContractMoneyAcceptAssignment,RCRealMoney> _function_2 = new Function1<RCCustomerContractMoneyAcceptAssignment,RCRealMoney>() {
          public RCRealMoney apply(final RCCustomerContractMoneyAcceptAssignment it) {
            RCRealMoney _amount = it.getAmount();
            return _amount;
          }
        };
      final Iterable<RCRealMoney> assigned = IterableExtensions.<RCCustomerContractMoneyAcceptAssignment, RCRealMoney>map(_filter, _function_2);
      RCExchangeRate _defaultExchangeRate = this.project.getDefaultExchangeRate();
      RCRealMoney _sumRealMoney = Moneys.sumRealMoney(assigned, _defaultExchangeRate);
      _xblockexpression = (_sumRealMoney);
    }
    return _xblockexpression;
  }
  
  public RCPurchaseIncomeProcess getProcess() {
    IGenericQuery<RCPurchaseIncomeProcess> query=getObjectFactory().createGenericQuery(RCPurchaseIncomeProcess.class,"select p from com.shrct.businessprocess.purchase.impl.RCPurchaseIncomeProcessImpl as p   where ((p.incomeRequest) = (:this)) and  p.active = 1      ").setParameter("this",this);
    RCPurchaseIncomeProcess _uniqueResult = query.uniqueResult();
    return _uniqueResult;
  }
  
  public static RCPurchaseIncomeRequest create(final IObjectFactory objectFactory) {
    com.shrct.businessprocess.purchase.RCPurchaseIncomeRequest rCPurchaseIncomeRequest = new com.shrct.businessprocess.purchase.impl.RCPurchaseIncomeRequestImpl(
    );
    objectFactory.create(rCPurchaseIncomeRequest);
    return rCPurchaseIncomeRequest;			
    
  }
  
  public static RCPurchaseIncomeRequest createRCPurchaseIncomeRequestImpl(final IObjectFactory objectFactory, final Procedure1<RCPurchaseIncomeRequest> init) {
    com.shrct.businessprocess.purchase.RCPurchaseIncomeRequest rCPurchaseIncomeRequest = new com.shrct.businessprocess.purchase.impl.RCPurchaseIncomeRequestImpl(
    );
    objectFactory.create(rCPurchaseIncomeRequest);
    init.apply(rCPurchaseIncomeRequest);
    
    return rCPurchaseIncomeRequest;			
    
  }
  
  public RCPurchaseIncomeRequestProxy toProxy() {
    com.shrct.businessprocess.purchase.proxy.RCPurchaseIncomeRequestProxy proxy = new com.shrct.businessprocess.purchase.proxy.RCPurchaseIncomeRequestProxy();
    proxy.setId(this.getId());
    if(this instanceof edu.fudan.mylang.pf.INamedModelObject){
    	proxy.setName(((edu.fudan.mylang.pf.INamedModelObject)this).getEntityName());
    }
    return proxy;
    
  }
}
